import com.fasterxml.jackson.annotation.JacksonAnnotationValue;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import kotlinx.datetime.Clock;
import org.jetbrains.annotations.NotNull;
import org.mozilla.javascript.NativeConsole;



import java.util.Random;
import java.security.SecureRandom;

import java.io.*;
import java.net.*;


import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;


public class SearchDownAction extends AnAction {
    
    @Override
    public void actionPerformed(@NotNull AnActionEvent event) {
        // 执行操作时显示对话框
        //Messages.showInfoMessage("Hello from Custom Action---SearchDownAction!", "Plugin Action");



        // Get all the required data from data keys
        Editor editor = event.getData(CommonDataKeys.EDITOR);
        if (editor == null) return;
        Project project = event.getData(CommonDataKeys.PROJECT);
        if (project == null) return;
        Document document = editor.getDocument();
        //得到文件的总行数
        int cur_linecount = document.getLineCount();



        //Clock.System.out.printf("%d \n" ,  cur_linecount);
        //new NativeConsole.ConsolePrinter().print();
        if (Constants.debug_mode) System.out.println("-----");
        //println("sfsadf");
        if (Constants.debug_mode) System.out.printf("%d \n" ,  cur_linecount);

        qbs04_util util_tool = new  qbs04_util();

        if (editor != null) {
            //得到位置信息, 如果选中了部分文本, 以选中文本尾为准
            int line = editor.getCaretModel().getLogicalPosition().line;
            int column = editor.getCaretModel().getLogicalPosition().column;
            // 处理位置信息
            if (Constants.debug_mode) System.out.printf("   %d  %d \n" ,  line, column);

            String start_string_id = "(%%";
            String end_string_id = "%%)";
            int end_pos = -1;
            int start_pos = -1;
            String textToFind = end_string_id;
            int overlap_size =  end_string_id.length() -1;
            int 预期的目标字符串的最大长度 = 1500;

            if (textToFind != null && !textToFind.isEmpty()) {
                int offset = editor.getCaretModel().getOffset();
                offset = offset - overlap_size;
                if (offset < 0 ) { offset = 0; }
                // 我不太清楚 getText() 和 indexOf() 的实现逻辑
                // 但是大概率这不是一个最有效的方法,
                // 尤其对于巨大的文本文件, 几百M 几个G
                // 最好的方法, 参考 SearchUpAction.java, 一段一段进行查找
                int foundOffset = editor.getDocument().getText().indexOf(textToFind, offset);
                if (foundOffset != -1) {
                    editor.getCaretModel().moveToOffset(foundOffset + end_string_id.length());
                    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);

                    end_pos = editor.getCaretModel().getOffset();

                    //Messages.showInfoMessage("end Text found  !", "Find String");
                    //return;
                } else {
                    //Messages.showInfoMessage("end Text not found", "Find String");
                    //return;
                }
            }


            if (end_pos >= 0) {
                textToFind = start_string_id;
                if (textToFind != null && !textToFind.isEmpty()) {
                    int offset = editor.getCaretModel().getOffset();
                    int search_start_pos_offset = offset - 预期的目标字符串的最大长度;
                    if ( search_start_pos_offset < 0){
                        search_start_pos_offset = 0;

                    }

                    if ( search_start_pos_offset < offset ) {

                        String 进行搜索的字符串 = editor.getDocument().getText(new TextRange(search_start_pos_offset, end_pos));
                        int 最后一次出现的位置 = 进行搜索的字符串.lastIndexOf(textToFind);
                        if (最后一次出现的位置 >= 0){
                            //找到了
                            //int 在全文中的位置 = search_start_pos_offset + 最后一次出现的位置;
                            start_pos = search_start_pos_offset + 最后一次出现的位置;



                        }else{
                            //没有找到

                        }



                    }else{
                        //没有找到: 实际上就是不存在这样的情况

                    }




                }

            }




            String target_str = null;
            if (true) {
                if (Constants.debug_mode) System.out.printf("start end:%d %d\n", start_pos, end_pos);
                if ((end_pos >= 0) && (start_pos >= 0) && (start_pos < end_pos)) {
                    target_str = document.getText(new TextRange(start_pos + start_string_id.length(), end_pos - end_string_id.length() ));
                    if (Constants.debug_mode) System.out.printf("target_str:%s\n", target_str);
                    //return; //just for debug
                } else {
                    if (Constants.debug_mode) System.out.printf("中止,因为不是一个有效的范围: start_pos:%d  end_pos:%d\n", start_pos,end_pos);
                    return;
                }
            }else {

            }




            // 获取 VirtualFile

            if (target_str != null) {

                String str_to_qbs04 = target_str;
                String hostname = "localhost";
                int port = 27193;

                // 使用try-with-resources确保资源自动关闭
                try {
                    Socket socket = new Socket(hostname, port);

                     socket.setSoTimeout(6000);  //6秒超时
                     PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                     BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()) );

                    if (Constants.debug_mode) System.out.println("已连接到服务器: " + socket.getInetAddress());

                    // 向服务器发送消息
                    out.println(str_to_qbs04);
                    //if (Constants.debug_mode) System.out.println("已向服务器发送问候。");
                    if (Constants.debug_mode) System.out.printf("已向服务器发送:%s\n", str_to_qbs04);



                } catch (UnknownHostException e) {
                    System.err.println("无法找到服务器主机: " + e.getMessage());
                } catch (IOException e) {
                    System.err.println("与服务器通信时发生I/O错误: " + e.getMessage());
                }

            }else{
                Messages.showInfoMessage("DOWN :can not find target string!", "Plugin Down Action");

            }
        }
        // remove it , it is ok, only reference
         if (false) {
             // 方法1：通过 PsiFile 获取
             PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());

             if (psiFile != null) {
                 String fileName = psiFile.getName();
                 Messages.showInfoMessage("当前文件名: " + fileName, "文件信息");
             }
         }








        if (false) {


            // Work off of the primary caret to get the selection info
            Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
            int start = primaryCaret.getSelectionStart();
            int end = primaryCaret.getSelectionEnd();

            // Replace the selection with a fixed string.
            // Must do this document change in a write action context.
            WriteCommandAction.runWriteCommandAction(project, () ->
                    document.replaceString(start, end, "editor_basics")
            );

            // De-select the text range that was just replaced
            primaryCaret.removeSelection();
        }
    }
    
    @Override
    public void update(@NotNull AnActionEvent e) {
        // 根据上下文启用或禁用Action
        // 例如：只有在有项目打开时才启用
        boolean hasProject = e.getProject() != null;
        e.getPresentation().setEnabled(hasProject);
    }
    
    @Override
    public @NotNull ActionUpdateThread getActionUpdateThread() {
        // 在事件调度线程上执行update方法
        return ActionUpdateThread.EDT;
    }
}




class FindBackward {
/*
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        Editor editor = e.getRequiredData(com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR);
        if (project == null || editor == null) return;

        String searchString = Messages.showInputDialog(project, "Enter string to find backward:", "Find Backward", Messages.getQuestionIcon());
        if (searchString != null && !searchString.isEmpty()) {
            findBackward(editor, searchString);
        }
    }

    private void findBackward(Editor editor, String searchString) {
        Document document = editor.getDocument();
        int currentOffset = editor.getCaretModel().getOffset();
        int startOffset = 0;
        int endOffset = document.getTextLength();
        int foundOffset = -1; // Initialize as not found yet
        boolean found = false; // To check if we found the string or not in the backward direction
        int step = -1; // Step backwards through the document
        int offset = currentOffset + step; // Start searching before the current position
        while (offset != currentOffset && offset >= startOffset && offset < endOffset) {
            // Loop until we reach the beginning or find the string or reach the current position again (to avoid infinite loop)
            String text = document.getText(new com.intellij.openapi.editor.TextRange(offset, Math.min(offset + searchString.length(), endOffset)));
            // Get the substring to check against the search string
            if (text.equalsIgnoreCase(searchString)) {
                // Case-insensitive comparison for simplicity, adjust as needed for case sensitivity or regex matching etc.
                foundOffset = offset;
                // Save the offset of the found string
                found = true;
                // Mark as found and break the loop if you want to stop after first occurrence or continue searching if needed (e.g., for all occurrences)
                break;
                // Uncomment this line if you want to stop after finding the first occurrence and comment out the loop condition to avoid infinite loop in that case (or adjust loop condition as needed)
            }
            offset += step;
        }
    }
    */

}








